package apiserver

import (
	"cs0512/fmr/internal/apiserver/config"
	"cs0512/fmr/internal/apiserver/options"
	"cs0512/fmr/internal/apiserver/store"
	"cs0512/fmr/internal/apiserver/store/mysql"
	"cs0512/fmr/internal/pkg/corn"
	"cs0512/fmr/internal/pkg/server"

	"github.com/marmotedu/log"

	"github.com/marmotedu/iam/pkg/shutdown"
	"github.com/marmotedu/iam/pkg/shutdown/shutdownmanagers/posixsignal"
)

// apiServer 对通用服务的封装
type apiServer struct {
	gs               *shutdown.GracefulShutdown
	genericAPIServer *server.GenericAPIServer
	gRPCAPIServer    *grpcAPIServer
}

// 预处理服务，封装了apiServer
type prepareAPIServer struct {
	*apiServer
}

// ExtraConfig 定义扩展配置
type ExtraConfig struct {
	// GRPC 服务监听地址
	Addr string

	// GRPC 密钥文件路径
	GRpcKeyFile string

	// GRPC 证书文件路径
	GRpcCertFile string

	// GRPC 消息最大长度
	MaxMsgSize int

	// TLS服务证书
	ServerCert options.GeneratableKeyCert

	// MySQL配置
	mysqlOptions *options.MySQLOptions
}

// 创建api服务实例
func createAPIServer(cfg *config.Config) (*apiServer, error) {
	// 优雅关停
	gs := shutdown.New()
	gs.AddShutdownManager(posixsignal.NewPosixSignalManager())

	// 创建通用服务
	genericConfig, err := buildGenericConfig(cfg)
	if err != nil {
		return nil, err
	}

	// 创建扩展配置
	extraConfig, err := buildExtraConfig(cfg)
	if err != nil {
		return nil, err
	}

	//genericServer := server.NewServer(genericConfig.Complete())
	genericServer, err := genericConfig.Complete().New()
	if err != nil {
		return nil, err
	}

	// 扩展服务，可以是GRPC服务
	rs, err := extraConfig.Complate().New()
	if err != nil {
		return nil, err
	}

	// 创建API服务实例 apiServer
	apiServerIns := &apiServer{
		gs:               gs,
		genericAPIServer: genericServer,
		gRPCAPIServer:    rs,
	}

	return apiServerIns, nil
}

// 通过apiServer 进行服务预处理，并返回预处理服务实例
func (s *apiServer) PrepareRun() prepareAPIServer {
	//初始化 gin路由 和必要的中间件
	initRouter(s.genericAPIServer.Engine)

	//corn autoTask
	initAutoTask(store.Client())

	// 注册服务关停的一些处理
	s.gs.AddShutdownCallback(shutdown.ShutdownFunc(func(string) error {
		mysqlStore, _ := mysql.GetMySQLFactoryOr(nil)
		if mysqlStore != nil {
			return mysqlStore.Close()
		}
		//自动任务
		corn.Stop()
		s.genericAPIServer.Close()
		s.gRPCAPIServer.Close()
		return nil
	}))

	return prepareAPIServer{s}
}

// 服务启动
func (s prepareAPIServer) Run() error {
	//启动 shutdown managers
	if err := s.gs.Start(); err != nil {
		log.Fatalf("start shutdown manager failed: %s", err.Error())
	}

	// 启动GRPC服务
	s.gRPCAPIServer.Run()

	//启动通用服务
	return s.genericAPIServer.Run()
}

// 展开配置的完整配置结构，暂时只封装了ExtraConfig
type CompleteExtraConfig struct {
	*ExtraConfig
}

// 扩展配置填充完成生成 完整扩展配置实例
func (c *ExtraConfig) Complate() *CompleteExtraConfig {
	if c.Addr == "" {
		c.Addr = "127.0.0.1:9090"
	}
	return &CompleteExtraConfig{c}
}

// 初始化扩展服务，如Mysql
func (c *CompleteExtraConfig) New() (*grpcAPIServer, error) {
	// 获取Mysql连接实例，并设置存储客户端
	storeIns, _ := mysql.GetMySQLFactoryOr(c.mysqlOptions)
	store.SetClient(storeIns)

	return &grpcAPIServer{
		address: c.Addr,
		key:     c.GRpcKeyFile,
		cert:    c.GRpcCertFile,
	}, nil
}

// 通过config.Config 即options.Options ，创建通用服务配置 server.Config
func buildGenericConfig(cfg *config.Config) (genericConfig *server.Config, lastErr error) {
	genericConfig = server.NewConfig()
	if lastErr = cfg.GenericServerRunOptions.ApplyTo(genericConfig); lastErr != nil {
		return
	}

	if lastErr = cfg.SecureServing.ApplyTo(genericConfig); lastErr != nil {
		return
	}

	if lastErr = cfg.InsecureServing.ApplyTo(genericConfig); lastErr != nil {
		return
	}
	return
}

// 创建扩展服务配置
func buildExtraConfig(cfg *config.Config) (*ExtraConfig, error) {
	exc := &ExtraConfig{
		Addr:         cfg.GRPCOptions.Addr,
		GRpcKeyFile:  cfg.GRPCOptions.Key,
		GRpcCertFile: cfg.GRPCOptions.Cert,
		MaxMsgSize:   1000,
		ServerCert:   cfg.SecureServing.ServerCert,
		mysqlOptions: cfg.MySQLOptions,
	}
	return exc, nil
}
